package com.macro.mall.controller.callbak;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

@Slf4j
@Service
public class XhsDecryptService {

    /**
     * 小红书消息解密服务
     */
    public String decrypt(String encryptedMsg, String encodingAesKey) {
        try {
            log.debug("开始解密小红书消息，密文长度: {}", encryptedMsg.length());

            // 1. Base64解码AES密钥
            byte[] aesKey = decodeAesKey(encodingAesKey);

            // 2. 初始化AES解密器
            Cipher cipher = initAesCipher(aesKey);

            // 3. Base64解码并解密
            byte[] decryptedBytes = doFinalDecryption(cipher, encryptedMsg);

            // 4. 解析小红书消息结构
            return parseXhsMessage(decryptedBytes);

        } catch (Exception e) {
            log.error("小红书消息解密失败，密文: {}, 错误: {}", encryptedMsg, e.getMessage(), e);
            throw new RuntimeException("小红书消息解密失败: " + e.getMessage());
        }
    }

    /**
     * Base64解码AES密钥
     */
    private byte[] decodeAesKey(String encodingAesKey) {
        try {
            // 小红书要求对43位的encodingAesKey补一个'='变成44位
            String key = encodingAesKey.length() == 43 ?
                    encodingAesKey + "=" : encodingAesKey;
            return Base64.decodeBase64(key);
        } catch (Exception e) {
            log.error("AES密钥Base64解码失败: {}", encodingAesKey, e);
            throw new RuntimeException("AES密钥格式错误");
        }
    }

    /**
     * 初始化AES解密器
     */
    private Cipher initAesCipher(byte[] aesKey) throws Exception {
        try {
            // 使用前16字节作为IV
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
            SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");

            // 小红书使用AES/CBC/PKCS5Padding模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            return cipher;
        } catch (Exception e) {
            log.error("AES解密器初始化失败", e);
            throw new Exception("AES解密器初始化失败: " + e.getMessage());
        }
    }

    /**
     * 执行最终解密
     */
    private byte[] doFinalDecryption(Cipher cipher, String encryptedMsg) throws Exception {
        try {
            // Base64解码密文
            byte[] encryptedBytes = Base64.decodeBase64(encryptedMsg);
            log.debug("Base64解码后密文长度: {}", encryptedBytes.length);

            // AES解密
            byte[] decrypted = cipher.doFinal(encryptedBytes);
            log.debug("AES解密后数据长度: {}", decrypted.length);
            return decrypted;
        } catch (Exception e) {
            log.error("AES解密失败，密文可能已损坏或密钥不正确", e);
            throw new Exception("AES解密失败: " + e.getMessage());
        }
    }

    /**
     * 解析小红书消息结构
     */
    private String parseXhsMessage(byte[] decrypted) throws Exception {
        try {
            // 小红书消息格式: [16字节随机字符串][4字节消息长度][消息内容][appId]
            if (decrypted.length < 20) {
                throw new Exception("解密后消息长度不足20字节");
            }

            // 解析消息长度(网络字节序)
            byte[] networkOrder = Arrays.copyOfRange(decrypted, 16, 20);
            int msgLength = recoverNetworkBytesOrder(networkOrder);

            // 检查消息长度是否有效
            if (msgLength < 0 || msgLength > decrypted.length - 20) {
                throw new Exception("无效的消息长度: " + msgLength);
            }

            // 提取消息内容
            String content = new String(
                    Arrays.copyOfRange(decrypted, 20, 20 + msgLength),
                    StandardCharsets.UTF_8);

            // 提取appId (可选)
            if (decrypted.length > 20 + msgLength) {
                String appId = new String(
                        Arrays.copyOfRange(decrypted, 20 + msgLength, decrypted.length),
                        StandardCharsets.UTF_8);
                log.debug("解析到appId: {}", appId);
            }

            log.debug("解密成功，消息内容: {}", content);
            return content;
        } catch (Exception e) {
            log.error("小红书消息解析失败", e);
            throw new Exception("消息解析失败: " + e.getMessage());
        }
    }

    /**
     * 还原4字节的网络字节序为整数
     */
    private static int recoverNetworkBytesOrder(byte[] orderBytes) {
        if (orderBytes == null || orderBytes.length != 4) {
            throw new IllegalArgumentException("无效的网络字节序");
        }
        int sourceNumber = 0;
        for (int i = 0; i < 4; i++) {
            sourceNumber <<= 8;
            sourceNumber |= orderBytes[i] & 0xff;
        }
        return sourceNumber;
    }

    /**
     * PKCS7解码（保留但当前未使用）
     */
    private static class PKCS7Decoder {
        public static byte[] decode(byte[] decrypted) {
            int pad = decrypted[decrypted.length - 1];
            if (pad < 1 || pad > 32) {
                pad = 0;
            }
            return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
        }
    }
}
